import logging
import requests
from seleniumwire import webdriver as wire_webdriver
from selenium.common.exceptions import UnexpectedAlertPresentException,WebDriverException
from fake_useragent import UserAgent
import time
import json
from urllib.parse import quote
from selenium.webdriver.common.by import By
chrome_options = wire_webdriver.ChromeOptions()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument("--ignore-certificate-errors")  # 忽略证书错误警告
chrome_options.add_argument("--ignore-ssl-errors")  # 忽略SSL错误警告
# chrome_options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片
# chrome_options.add_argument('--headless')  # 设置为无头模式

class XinbangWechat:
    def __init__(self) -> None:
        self.user_agent = UserAgent(browsers=["chrome"],platforms=["pc"]).random

    def wait_request(self, driver, exclude=[]):
        time.sleep(0.5)
        jud = True
        while (jud):
            response_list = []
            requests = driver.requests
            for request in requests:
                if request.url.split('?')[0].split('/')[-1] not in exclude:
                    response_list.append(request.response != None)
                    if request.response == None:
                        print(request.url)

            # print(response_list)
            if all(response_list):
                jud = False
                logging.error('所有请求加载完成')
        time.sleep(0.5)
    
    def get_cookies_and_ntoken(self, driver):
        data = {
            'ntoken':'',
            'cookie':''
        }
        requests_list = driver.requests
        for request in requests_list:
            if request.url.split('?')[0].split('/')[-1] in ['getLoginUser']:
                data['ntoken'] = request.url.split('?')[-1].split('=')[-1]
                for k,v in request.headers.items():
                    if k == 'Cookie':
                        data['cookie'] = v
                        break
        lis = data.values()
        if all(lis):
            # 把字典保存为json文件
            with open('headers.json','w') as f:
                json.dump(data,f)
            return True
        return False

    def xinbang_wechat_login_method(self):
        # url = f'https://newrank.cn/'
        # url = f'https://newrank.cn/user/login'
        url = f'https://mp.weixin.qq.com/'
        chrome_options.add_argument("--user-agent=" + self.user_agent) 
        driver = wire_webdriver.Chrome(options=chrome_options)

        try:
            driver.maximize_window()
            driver.get(url)
            time.sleep(0.5)
            # element = driver.find_element(By.XPATH, "//div[div/div/div/text()='登录/注册']")
            # element.click()
            self.wait_request(driver, exclude=['getEwmSubNotice', 'about-newrank.mp4'])
            # element = driver.find_element(By.XPATH, "//img[@alt='二维码']")
            element = driver.find_element(By.XPATH, "//img[@class='login__type__container__scan__qrcode']")
            logging.error('请扫码登录base64:')
            image_url = element.get_attribute("src") 
            print(image_url)
            base64_image = driver.execute_script("""  
            return new Promise((resolve, reject) => {  
                var img = new Image();  
                img.src = arguments[0];  
                img.crossOrigin = 'Anonymous'; // 设置跨域  
                img.onload = function() {  
                    var canvas = document.createElement('canvas');  
                    canvas.width = img.width;  
                    canvas.height = img.height;  
                    var ctx = canvas.getContext('2d');  
                    ctx.drawImage(img, 0, 0);  
                    resolve(canvas.toDataURL().split(',')[1]); // 返回Base64部分  
                };  
                img.onerror = function() {  
                    reject('Error loading image.');  
                };  
            });  
            """, image_url)  
            print(base64_image)
            # driver.execute_script("window.open();")

            # # 获取所有窗口句柄
            # window_handles = driver.window_handles

            # # 切换到新打开的标签页（假设新标签页总是在列表的最后一个）
            # new_tab_handle = window_handles[-1]
            # driver.switch_to.window(new_tab_handle)

            # # 加载新地址
            # driver.get(login_img)

            # # 获取页面内容，例如获取页面的HTML
            # page_source = driver.page_source
            # logging.error(page_source)

            # logging.error(login_img)
            # TODO 首次运行时,需要扫码登录,将该照片的url存入数据库
            while True:
                try:
                    element = driver.find_element(By.XPATH, "//span[text()='个人中心']")
                    logging.error('登录成功!')
                    # TODO 在数据库中标记已登录
                    break
                except:
                    try:
                        element = driver.find_element(By.XPATH, "//button[span/text()='刷新']")
                        element.click()
                        logging.error('二维码超时,正在刷新!')
                        self.wait_request(driver, exclude=['getEwmSubNotice', 'about-newrank.mp4'])
                        element = driver.find_element(By.XPATH, "//img[@alt='二维码']")
                        login_img = element.get_attribute('src')
                        logging.error(login_img)
                        # TODO 超时刷新后,需将该照片的url在数据库的数据覆盖
                    except:
                        pass
            cookies = driver.get_cookies()
            with open('cookies.json', 'w') as f:
                json.dump(cookies, f)
            return cookies
            
        except UnexpectedAlertPresentException as e:
            logging.error('弹窗：')
            logging.error(e.alert_text)
            return []
        except WebDriverException as e:
            logging.error(str(e))
            logging.error(f'[{url}]不可达!')
            time.sleep(100)
            return ["can't reach"]
        except Exception as e:
            logging.error('spider_by_selenium_wire wrong:')
            logging.error(e)
            return []
        finally:
            if driver:
                driver.quit()
    
    def xinbang_wechat_keep_method(self):
        url = f'https://newrank.cn/'
        chrome_options.add_argument("--user-agent=" + self.user_agent) 
        driver = wire_webdriver.Chrome(options=chrome_options)
        with open('cookies.json', 'r') as f:
            cookies = json.load(f)

        try:
            # 打开网页
            driver.maximize_window()
            driver.get(url)
            time.sleep(0.5)

            for cookie in cookies:
                driver.add_cookie(cookie)
            
            driver.refresh()
            self.get_cookies_and_ntoken(driver)

            start_time = time.time()
            while True:
                end_time = time.time()
                if not (end_time-start_time) % 60:
                    driver.refresh()
                    self.get_cookies_and_ntoken(driver)

        except UnexpectedAlertPresentException as e:
            logging.error('弹窗：')
            logging.error(e.alert_text)
            return []
        except WebDriverException as e:
            logging.error(str(e))
            logging.error(f'[{url}]不可达!')
            time.sleep(100)
            return ["can't reach"]
        except Exception as e:
            logging.error('spider_by_selenium_wire wrong:')
            logging.error(e)
            return []
        finally:
            if driver:
                driver.quit()
    
    def search_by_requests(self, method:list, keyword:str, page:int=1):
        """
        调用接口搜索数据
        :param method: 请求方法,1是名称;2是账号id;3是简介;4是企业;5是互选账号
        例如[1,2,3,4]
        """
        url = 'https://gw.newrank.cn/api/mainSearch/nr/mainSearch/account/search2'

        with open('headers.json', 'r') as f:
            data = json.load(f)

        headers = {
            'User-Agent': self.user_agent,
            'Content-Type': 'application/json',
            'cookie':data.get('cookie',''),
            'N-token':data.get('ntoken','')
        }

        payload = {
            "start": page,
            "size": 10,
            "keyword": f"k%3D{quote(keyword)}",
            "platform": "gzh",
            "type": method,
            "sort": "0",
            "sortType": "desc",
            "accountType": "",
            "nrIndexWeekRangeList": [],
            "readCountRangeList": [],
            "watchCountRangeList": [],
            "likeCountRangeList": [],
            "searchSource": 1,
            "queryType": 1
        }

        # Make the request with cookies and payload
        response = requests.post(url, headers=headers, json=payload)
        return response.json()

    def search_articles_by_requests(self, account:str):
        """
        调用接口搜索数据
        :param account: 微信公众号id
        """
        url = 'https://gw.newrank.cn/api/wechat/xdnphb/detail/v1/rank/article/lists'

        # 读取headers.json文件数据为字典

        with open('headers.json', 'r') as f:
            data = json.load(f)

        headers = {
            'User-Agent': self.user_agent,
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
            'cookie':data.get('cookie',''),
            'N-token':data.get('ntoken','')
        }

        payload = {
            "account": account
        }

        response = requests.post(url, headers=headers, data=payload)
        if response.status_code == 200:
            return response.json().get('value',{}).get('articles')
        return {}
    
def keep_it():
    try:
        css = XinbangWechat()
        css.xinbang_wechat_login_method()
        css.xinbang_wechat_keep_method()
    finally:
        pass
    
    
if __name__ == '__main__':
    keep_it()
    # css = XinbangWechat()
    # print(css.search_by_requests(method=[1]))
    # print(css.search_articles_by_requests('qiluwanbaoqlwb'))
    